package swingFiles;

import javax.swing.JPanel;
import java.awt.Color;
import javax.swing.JLabel;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.JComboBox;
import javax.swing.JButton;

import mainFiles.GmsDB;
import mainFiles.Instructor;
import mainFiles.Location;
import mainFiles.Class;

/**
 * Creates the pane to allow users to edit a class within the database system.
 * 
 * @author Emily Linniman
 * @version December 1, 2014
 *
 */
@SuppressWarnings("serial")
public class EditClassPanel extends JPanel {
	
	/** The field to input the id of the class to be edited. */
	private JTextField idField;
	
	/** The field to input the attribute of the class to be edited. */
	private JTextField attributeField;
	
	/** The database object to interact with the database with. */
	private GmsDB db;
	
	/** The frame the panel is on. */
	private JFrame my_frame;

	/**
	 * Create the panel.
	 */
	public EditClassPanel(JFrame the_frame, final JPanel previous_panel) {
		my_frame = the_frame;
		db = new GmsDB();
		
		setBackground(Color.ORANGE);
		setLayout(null);
		
		JLabel headerLabel = new JLabel("Edit Class");
		headerLabel.setFont(new Font("Arial", Font.PLAIN, 18));
		headerLabel.setBounds(179, 6, 86, 16);
		add(headerLabel);
		
		JLabel classIdLabel = new JLabel("Class ID");
		classIdLabel.setFont(new Font("Arial", Font.PLAIN, 15));
		classIdLabel.setBounds(111, 49, 61, 16);
		add(classIdLabel);
		
		idField = new JTextField();
		idField.setHorizontalAlignment(SwingConstants.CENTER);
		idField.setBounds(242, 43, 134, 28);
		add(idField);
		idField.setColumns(9);
		
		JLabel lblChooseClassAttribute = new JLabel("Choose class attribute to edit:");
		lblChooseClassAttribute.setFont(new Font("Arial", Font.PLAIN, 15));
		lblChooseClassAttribute.setBounds(135, 95, 201, 16);
		add(lblChooseClassAttribute);
		
		final Map<String, String> attributeMap = new TreeMap<String, String>();
		attributeMap.put("ID", "classID");
		attributeMap.put("Name", "className");
		attributeMap.put("Size", "classSizeAvailability");
		attributeMap.put("Cost",  "classPrice");
		attributeMap.put("Days", "classDay");
		attributeMap.put("Time", "classTime");
		attributeMap.put("Description",  "classDescription");
		attributeMap.put("Instructor", "Instructor_User_userID");
		attributeMap.put("Location", "Location_locationID");
		
		final JComboBox attributeComboBox = new JComboBox();
		attributeComboBox.addItem("");
		Set<String> keys = attributeMap.keySet();
		for (String key : keys) {
			attributeComboBox.addItem(key);
		}
		attributeComboBox.setFont(new Font("Arial", Font.PLAIN, 15));
		attributeComboBox.setBounds(135, 123, 201, 27);
		add(attributeComboBox);
		
		JLabel editInstructionsLabel = new JLabel("Enter new attribute value:");
		editInstructionsLabel.setFont(new Font("Arial", Font.PLAIN, 15));
		editInstructionsLabel.setBounds(145, 162, 170, 16);
		add(editInstructionsLabel);
		
		attributeField = new JTextField();
		attributeField.setHorizontalAlignment(SwingConstants.CENTER);
		attributeField.setBounds(155, 190, 134, 28);
		add(attributeField);
		attributeField.setColumns(200);
		
		JButton applyButton = new JButton("Apply");
		applyButton.setFont(new Font("Arial", Font.PLAIN, 15));
		applyButton.setBounds(111, 243, 117, 29);
		applyButton.addActionListener(new ActionListener() {
			
			//Checks to see if the input data is valid
			//If data is valid, edits the class in the database system
			//If not valid, shows error message
			public void actionPerformed(ActionEvent arg0) {
				boolean success = true;
				String failedElement = null;
				
				String id = idField.getText();
				boolean foundID = false;
				try {
					List<Class> classes = db.getClasses();
					for (Class currClass : classes) {
						if (currClass.getID().equals(id))
							foundID = true;
					}
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
				if (!foundID) {
					success = false;
					failedElement = "ID";
				}
				
				
				
				String attributeName = (String)attributeComboBox.getSelectedItem();
				String columnName = null;
				Object newData = null;
				
				if (attributeName == null) {
					success = false;
					failedElement = "Attribute Name";
				} else {
					columnName = attributeMap.get(attributeName);
					newData = attributeField.getText();
					
					if (attributeName.equals("ID")) {
						if (((String) newData).length() != 9 && !isNumber((String)newData)) {
							success = false;
							failedElement = "ID";
						} else {
							try {
								List<Class> classes = db.getClasses();
								for (Class currClass : classes) {
									if (currClass.getID().equals((String)newData)) {
										success = false;
										failedElement = "ID";
									}
								}
							} catch (SQLException e) {
								e.printStackTrace();
							}
							
						}
					} else if (attributeName.equals("Size") && !isInteger((String)newData)) {
						success = false;
						failedElement = "Size";
					} else if (attributeName.equals("Name") && ((String) newData).length() > 25 || ((String)newData).length() < 1) {
						success = false;
						failedElement = "Name";
					} else if (attributeName.equals("Cost") && !isNumber((String)newData)) {
						success = false;
						failedElement = "Cost";
					} else if (attributeName.equals("Days")) {
						if (!isDate((String)newData)) {
							success = false;
							failedElement = "Date";
						}
					} else if (attributeName.equals("Time")) {
						if (!isTime((String)newData)) {
							success = false;
							failedElement = "Time";
						}
					} else if (attributeName.equals("Instructor")) {
						try {
							List<Instructor> instructors = db.getInstructors();
							boolean foundInstructor = false;
							for (Instructor currInstructor : instructors) {
								if (currInstructor.getID().equals(newData))
									foundInstructor = true;
							}
							if (!foundInstructor) {
								success = false;
								failedElement = "Instructor";
							}
						} catch (SQLException e) {
							e.printStackTrace();
						}
						
					} else if (attributeName.equals("Location")) {
						List<Location> locations;
						try {
							locations = db.getLocations();
							boolean foundLocation = false;
							for (Location currLocation : locations) {
								if (currLocation.getLocationID().equals(newData))
									foundLocation = true;
							}
							if (!foundLocation) {
								success = false;
								failedElement = "Location";
							}
						} catch (SQLException e) {
							e.printStackTrace();
						}	
						
					} else if (attributeName.equals("Description") && ((String) newData).length() > 160) {
						success = false;
						failedElement = "Description";
					}
				}
				
				if (success) {
					db.updateClass(id, columnName, newData);
					JOptionPane.showMessageDialog(my_frame, "Class sucessfully updated!", "Success!", JOptionPane.PLAIN_MESSAGE);
				} else {
					JOptionPane.showMessageDialog(my_frame, "Class update failed. Please enter a valid " + failedElement, "Error!", JOptionPane.ERROR_MESSAGE);
				}
				
			}

		});
		add(applyButton);
		
		JButton backButton = new JButton("Back");
		backButton.setFont(new Font("Arial", Font.PLAIN, 15));
		backButton.setBounds(259, 243, 117, 29);
		backButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				my_frame.setContentPane(previous_panel);
				my_frame.validate();
				my_frame.setVisible(true);
			}
		});
		add(backButton);

	}
	
	/**
	 * Checks to see if the given string is a number
	 * 
	 * @param st the string to check if it is a number
	 * @return true if the string is a number, false otherwise
	 */
	private boolean isNumber(String st) {
		boolean success = true;
		try {
			Double.parseDouble(st);
		}
		catch(NumberFormatException e) {
			success = false;
		}
		return success;
	}
	
	/**
	 * Checks to see if the given string is an integer
	 * 
	 * @param st the string to check if it is an integer
	 * @return true if the string is an integer, false otherwise
	 */
	private boolean isInteger(String st) {
		boolean success = true;
		try {
			Integer.parseInt(st);
		} catch(NumberFormatException e) {
			success = false;
		}
		
		return success;
	}
	/**
	 * Checks if the string given is a valid date.
	 * 
	 * @param date the string to check for validity
	 * @return true if the date is valid, false otherwise
	 */
	private boolean isDate(String date) {
		try {
			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
			dateFormat.setLenient(false);
			dateFormat.parse(date);	
			return true;
		} catch (ParseException e) {
			return false;
		}
	}
	
	/**
	 * Checks to see if the string given is a valid time.
	 * 
	 * @param time the string to check for validity
	 * @return true if the time is valid, false otherwise
	 */
	private boolean isTime(String time) {
		try {
			DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
			timeFormat.setLenient(false);
			timeFormat.parse(time);
			return true;
		} catch(ParseException e) {
			return false;
		}
	}
}
